using UniversalAdmin.Application.Services;
using UniversalAdmin.Domain.Entities;
using UniversalAdmin.Domain.Interfaces;
using Microsoft.AspNetCore.Http;

namespace UniversalAdmin.Infrastructure.Services
{
    /// <summary>
    /// 用户认证服务实现
    /// </summary>
    public class AuthService : IAuthService
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IPasswordHasher _passwordHasher;
        private readonly IJwtService _jwtService;
        private readonly IHttpContextAccessor _httpAccessor;

        public AuthService(
            IUnitOfWork unitOfWork,
            IPasswordHasher passwordHasher,
            IJwtService jwtService,
            IHttpContextAccessor httpAccessor)
        {
            _unitOfWork = unitOfWork;
            _passwordHasher = passwordHasher;
            _jwtService = jwtService;
            _httpAccessor = httpAccessor;
        }

        /// <summary>
        /// 验证用户凭据
        /// </summary>
        public async Task<User?> ValidateUserAsync(string username, string password)
        {
            if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(password))
                return null;

            // 获取用户（包含角色信息）
            var user = await _unitOfWork.UserRepository.GetByUsernameAsync(username);
            if (user == null)
                return null;

            // 验证密码
            if (!_passwordHasher.Verify(password, user.Password))
                return null;

            // 检查用户是否激活
            if (!user.IsActive)
                return null;

            return user;
        }

        /// <summary>
        /// 获取用户角色
        /// </summary>
        public async Task<IEnumerable<string>> GetUserRolesAsync(int userId)
        {
            var user = await _unitOfWork.UserRepository.GetUserWithRolesAsync(userId);
            if (user?.UserRoles == null)
                return Array.Empty<string>();

            return user.UserRoles
                .Where(ur => ur.Role != null)
                .Select(ur => ur.Role!.Name)
                .ToList();
        }

        /// <summary>
        /// 登录
        /// </summary>
        public async Task<LoginResult> LoginAsync(string usernameOrEmail, string password)
        {
            try
            {
                // 验证用户凭据（支持用户名或邮箱登录）
                User? user = null;

                // 先尝试按用户名查询
                user = await _unitOfWork.UserRepository.GetByUsernameAsync(usernameOrEmail);

                // 如果用户名查询失败，尝试按邮箱查询
                if (user == null)
                {
                    user = await _unitOfWork.UserRepository.GetByEmailAsync(usernameOrEmail);
                }

                // 验证用户和密码
                if (user == null || !_passwordHasher.Verify(password, user.Password) || !user.IsActive)
                {
                    return new LoginResult
                    {
                        Success = false,
                        ErrorMessage = "用户名或密码错误"
                    };
                }

                // 获取用户角色
                var roles = await GetUserRolesAsync(user.Id);

                // 生成JWT Token
                var accessToken = _jwtService.GenerateAccessToken(user.Id, user.Username, roles);
                var refreshToken = _jwtService.GenerateRefreshToken();

                // 存储刷新令牌到数据库
                var ctx = _httpAccessor.HttpContext;
                var ip = GetClientIpAddress(ctx);
                var ua = ctx?.Request.Headers["User-Agent"].ToString();

                var refreshTokenEntity = new RefreshToken
                {
                    Token = refreshToken,
                    UserId = user.Id,
                    ExpiresAt = DateTime.UtcNow.AddDays(7), // 7天过期
                    IpAddress = ip,
                    UserAgent = ua,
                    CreatedAt = DateTime.UtcNow
                };

                await _unitOfWork.RefreshTokenRepository.AddAsync(refreshTokenEntity);

                await _unitOfWork.OperationLogRepository.AddAsync(new OperationLog
                {
                    UserId = user.Id,
                    Action = "auth.login",
                    Resource = "auth",
                    IpAddress = ip,
                    UserAgent = ua
                });
                await _unitOfWork.SaveChangesAsync();

                return new LoginResult
                {
                    Success = true,
                    AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    ExpiresIn = 30 * 60, // 30 minutes
                    User = new UserInfo
                    {
                        Id = user.Id,
                        Username = user.Username,
                        Email = user.Email,
                        Roles = roles
                    }
                };
            }
            catch (Exception ex)
            {
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = $"登录失败: {ex.Message}"
                };
            }
        }

        /// <summary>
        /// 注册用户
        /// </summary>
        public async Task<LoginResult> RegisterAsync(string username, string email, string password)
        {
            try
            {
                // 验证输入
                if (string.IsNullOrWhiteSpace(username) || string.IsNullOrWhiteSpace(email) || string.IsNullOrWhiteSpace(password))
                {
                    return new LoginResult
                    {
                        Success = false,
                        ErrorMessage = "用户名、邮箱和密码不能为空"
                    };
                }

                // 检查用户名是否已存在
                var existingUserByUsername = await _unitOfWork.UserRepository.GetByUsernameAsync(username);
                if (existingUserByUsername != null)
                {
                    return new LoginResult
                    {
                        Success = false,
                        ErrorMessage = "用户名已存在"
                    };
                }

                // 检查邮箱是否已存在
                var existingUserByEmail = await _unitOfWork.UserRepository.GetByEmailAsync(email);
                if (existingUserByEmail != null)
                {
                    return new LoginResult
                    {
                        Success = false,
                        ErrorMessage = "邮箱已存在"
                    };
                }

                // 创建新用户
                var hashedPassword = _passwordHasher.Hash(password);
                var newUser = new User
                {
                    Username = username,
                    Email = email,
                    Password = hashedPassword,
                    IsActive = true,
                    CreatedAt = DateTime.UtcNow
                };

                await _unitOfWork.UserRepository.AddAsync(newUser);
                await _unitOfWork.SaveChangesAsync();

                // 为新用户分配默认角色（普通用户角色）
                var defaultRole = await _unitOfWork.RoleRepository.GetByNameAsync("User");
                if (defaultRole != null)
                {
                    await _unitOfWork.ExecuteSqlRawAsync(
                        "INSERT INTO user_roles (user_id, role_id) VALUES ({0}, {1})",
                        newUser.Id, defaultRole.Id);
                }
                await _unitOfWork.SaveChangesAsync();

                // 获取用户角色
                var roles = await GetUserRolesAsync(newUser.Id);

                // 生成JWT Token
                var accessToken = _jwtService.GenerateAccessToken(newUser.Id, newUser.Username, roles);
                var refreshToken = _jwtService.GenerateRefreshToken();

                // 存储刷新令牌到数据库
                var refreshTokenEntity = new RefreshToken
                {
                    Token = refreshToken,
                    UserId = newUser.Id,
                    ExpiresAt = DateTime.UtcNow.AddDays(7), // 7天过期
                    CreatedAt = DateTime.UtcNow
                };

                await _unitOfWork.RefreshTokenRepository.AddAsync(refreshTokenEntity);

                return new LoginResult
                {
                    Success = true,
                    AccessToken = accessToken,
                    RefreshToken = refreshToken,
                    ExpiresIn = 30 * 60, // 30 minutes
                    User = new UserInfo
                    {
                        Id = newUser.Id,
                        Username = newUser.Username,
                        Email = newUser.Email,
                        Roles = roles
                    }
                };
            }
            catch (Exception ex)
            {
                return new LoginResult
                {
                    Success = false,
                    ErrorMessage = $"注册失败: {ex.Message}"
                };
            }
        }

        /// <summary>
        /// 刷新访问令牌
        /// </summary>
        public async Task<RefreshTokenResult> RefreshTokenAsync(string refreshToken)
        {
            try
            {
                // 验证刷新令牌格式
                if (!_jwtService.ValidateRefreshToken(refreshToken))
                {
                    return new RefreshTokenResult
                    {
                        Success = false,
                        ErrorMessage = "无效的刷新令牌格式"
                    };
                }

                // 从数据库获取刷新令牌
                var storedRefreshToken = await _unitOfWork.RefreshTokenRepository.GetByTokenAsync(refreshToken);
                if (storedRefreshToken == null)
                {
                    return new RefreshTokenResult
                    {
                        Success = false,
                        ErrorMessage = "刷新令牌不存在"
                    };
                }

                // 检查令牌是否有效
                if (!storedRefreshToken.IsValid)
                {
                    // 如果令牌已被撤销，可能是重放攻击
                    if (storedRefreshToken.IsRevoked)
                    {
                        // 记录安全事件
                        var context = _httpAccessor.HttpContext;
                        var clientIp = GetClientIpAddress(context);
                        
                        await _unitOfWork.OperationLogRepository.AddAsync(new OperationLog
                        {
                            UserId = storedRefreshToken.UserId,
                            Action = "auth.token_reuse_detected",
                            Resource = "security",
                            IpAddress = clientIp,
                            UserAgent = context?.Request.Headers["User-Agent"].ToString()
                        });
                        await _unitOfWork.SaveChangesAsync();
                    }
                    
                    return new RefreshTokenResult
                    {
                        Success = false,
                        ErrorMessage = storedRefreshToken.IsRevoked ? "刷新令牌已被使用" : "刷新令牌已过期"
                    };
                }

                // 获取用户信息
                var user = storedRefreshToken.User;
                if (user == null || !user.IsActive)
                {
                    return new RefreshTokenResult
                    {
                        Success = false,
                        ErrorMessage = "用户不存在或已被禁用"
                    };
                }

                // 获取用户角色
                var roles = await GetUserRolesAsync(user.Id);

                // 生成新的访问令牌和刷新令牌
                var newAccessToken = _jwtService.GenerateAccessToken(user.Id, user.Username, roles);
                var newRefreshToken = _jwtService.GenerateRefreshToken();

                // 重要：标记旧的刷新令牌为已使用
                storedRefreshToken.IsRevoked = true;
                storedRefreshToken.RevokedAt = DateTime.UtcNow;

                // 创建新的刷新令牌
                var ctx = _httpAccessor.HttpContext;
                var ip = ctx?.Connection.RemoteIpAddress?.ToString();
                var ua = ctx?.Request.Headers["User-Agent"].ToString();

                var newRefreshTokenEntity = new RefreshToken
                {
                    Token = newRefreshToken,
                    UserId = user.Id,
                    ExpiresAt = DateTime.UtcNow.AddDays(7),
                    IpAddress = ip,
                    UserAgent = ua,
                    CreatedAt = DateTime.UtcNow
                };

                await _unitOfWork.RefreshTokenRepository.AddAsync(newRefreshTokenEntity);
                await _unitOfWork.SaveChangesAsync();

                return new RefreshTokenResult
                {
                    Success = true,
                    AccessToken = newAccessToken,
                    RefreshToken = newRefreshToken,
                    ExpiresIn = 30 * 60 // 30 minutes
                };
            }
            catch (Exception ex)
            {
                return new RefreshTokenResult
                {
                    Success = false,
                    ErrorMessage = $"刷新令牌失败: {ex.Message}"
                };
            }
        }

        private static string GetClientIpAddress(HttpContext? context)
        {
            if (context == null)
                return "Unknown";

            // 首先检查代理头（如果通过反向代理）
            var forwardedFor = context.Request.Headers["X-Forwarded-For"].FirstOrDefault();
            if (!string.IsNullOrEmpty(forwardedFor))
            {
                // X-Forwarded-For 可能包含多个IP，取第一个
                var ip = forwardedFor.Split(',')[0].Trim();
                if (!string.IsNullOrEmpty(ip))
                    return ip;
            }

            // 检查 X-Real-IP 头
            var realIp = context.Request.Headers["X-Real-IP"].FirstOrDefault();
            if (!string.IsNullOrEmpty(realIp))
                return realIp;

            // 获取远程IP地址
            var remoteIp = context.Connection.RemoteIpAddress;
            if (remoteIp != null)
            {
                // 如果是IPv6的本地环回地址，转换为IPv4
                if (remoteIp.ToString() == "::1")
                    return "127.0.0.1";
                
                // 如果是IPv6地址，但不是本地环回，保持原样
                return remoteIp.ToString();
            }

            return "Unknown";
        }
    }
}
